package com.roy.bloom;

import static com.google.common.base.Preconditions.checkArgument;

import java.math.RoundingMode;
import java.util.Arrays;

import javax.annotation.Nullable;

import com.google.common.math.LongMath;
import com.google.common.primitives.Ints;
/**
 * 从guava里捞出来的内部类
 * @author roykingw 2019年8月6日
 *
 */
public class BitArray {
	// Note: We use this instead of java.util.BitSet because we need access to the long[] data field

	BitArray(long bits) {
	      this(new long[Ints.checkedCast(LongMath.divide(bits, 64, RoundingMode.CEILING))]);
	    }

	// Used by serialization
	BitArray(long[] data) {
	      checkArgument(data.length > 0, "data length is zero!");
	      this.data = data;
	      long bitCount = 0;
	      for (long value : data) {
	        bitCount += Long.bitCount(value);
	      }
	      this.bitCount = bitCount;
	    }

	
	final long[] data;
	long bitCount;
	
	/** Returns true if the bit changed value. */
	boolean set(long index) {
		if (!get(index)) {
			data[(int) (index >>> 6)] |= (1L << index);
			bitCount++;
			return true;
		}
		return false;
	}

	boolean get(long index) {
		return (data[(int) (index >>> 6)] & (1L << index)) != 0;
	}

	/** Number of bits */
	long bitSize() {
		return (long) data.length * Long.SIZE;
	}

	/** Number of set bits (1s) */
	long bitCount() {
		return bitCount;
	}

	BitArray copy() {
		return new BitArray(data.clone());
	}

	/** Combines the two BitArrays using bitwise OR. */
	void putAll(BitArray array) {
		checkArgument(data.length == array.data.length,
				"BitArrays must be of equal length (%s != %s)", data.length,
				array.data.length);
		bitCount = 0;
		for (int i = 0; i < data.length; i++) {
			data[i] |= array.data[i];
			bitCount += Long.bitCount(data[i]);
		}
	}

	@Override
	public boolean equals(@Nullable Object o) {
		if (o instanceof BitArray) {
			BitArray bitArray = (BitArray) o;
			return Arrays.equals(data, bitArray.data);
		}
		return false;
	}

	@Override
	public int hashCode() {
		return Arrays.hashCode(data);
	}
}
